use std::ops::Deref;
use std::time::Instant;

use clap::{arg, ArgMatches, Command};
use console::style;
use indicatif::{HumanDuration, MultiProgress, ProgressBar};
use sqlx::sqlite::SqliteQueryResult;
use tracing::error;

use crate::db::{DATABASES, DatabaseSet, init_database};
use crate::env::init_env;
use crate::log::init_logger;
use crate::spider::bili::album::crawl_bili_album;
use crate::spider::bili::BiliLoginCredential;
use crate::spider::bili::user::crawl_bili_user;
use crate::ui::main_window::show_ui;
use crate::utils::pbar::PB_SPINNER_STYLE;

mod cli;
mod db;
mod env;
mod http;
mod log;
mod models;
mod spider;
mod task;
mod utils;
mod collect;
mod ui;
mod error;

fn cli() -> Command {
    Command::new("Fast spider")
        .about("个人使用的开源抓取工具")
        .version("0.0.1")
        .subcommand_help_heading("帮助")
        .subcommand_required(false)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(
            Command::new("crawl")
                .about("抓取数据")
                .subcommand_required(true)
                .allow_external_subcommands(true)
                .subcommand(
                    Command::new("bili")
                        .about("抓取哔哩哔哩")
                        .subcommand_required(false)
                        .arg_required_else_help(false)
                ),
        )
        .subcommand(
            Command::new("collect")
                .about("归集抓取的数据")
                .arg_required_else_help(true)
                .arg(arg!(-p --picture "归集抓取到的动态、专栏、文章中的图片")),
        )
        .subcommand(
            Command::new("download")
                .about("下载指定的数据")
                .arg_required_else_help(true)
                .arg(arg!(--thumbnail "图片的缩略图")),
        )
        .subcommand(
            Command::new("calculate")
                .about("计算指定的字段")
                .subcommand_required(true)
                .subcommand(
                    Command::new("picture")
                        .about("计算图片的相关字段或属性")
                        .arg_required_else_help(true)
                        .arg(arg!(-p --phash "计算图片的感知哈希"))
                        .arg(arg!(-d --dhash "计算图片的差异哈希")),
                ),
        )
}

async fn handle_matches(matches: ArgMatches) {
    let guard = DATABASES[&DatabaseSet::DEFAULT].lock().await;
    let db = guard.deref();
    match matches.subcommand() {
        Some(("crawl", crawl_matches)) => match crawl_matches.subcommand() {
            Some(("bili", _crawl_matches)) => {
                let started = Instant::now();
                let multi = MultiProgress::new();

                let pb = multi.add(ProgressBar::new(9));
                pb.set_style(PB_SPINNER_STYLE.clone());
                pb.set_prefix(format!("{} 抓取用户：", style("[1/5]").bold().dim()));
                let credential = BiliLoginCredential::default();
                let qr = crawl_bili_user(&credential, 260888).await;
                pb.finish_with_message(format!("完成，新加入用户 {} 人", qr.rows_affected()));

                let pb = multi.add(ProgressBar::new(9));
                pb.set_style(PB_SPINNER_STYLE.clone());
                pb.set_prefix(format!("{} 抓取视频：", style("[2/5]").bold().dim()));
                pb.finish_with_message("完成");

                let pb = multi.add(ProgressBar::new(9));
                pb.set_style(PB_SPINNER_STYLE.clone());
                pb.set_prefix(format!("{} 抓取音频：", style("[3/5]").bold().dim()));
                pb.finish_with_message("完成");

                let pb = multi.add(ProgressBar::new(9));
                pb.set_style(PB_SPINNER_STYLE.clone());
                pb.set_prefix(format!("{} 抓取专栏：", style("[4/5]").bold().dim()));
                pb.finish_with_message("完成");

                let pb = multi.add(ProgressBar::new(9));
                pb.set_style(PB_SPINNER_STYLE.clone());
                pb.set_prefix(format!("{} 抓取动态：", style("[5/5]").bold().dim()));
                pb.set_message("正在更新动态清单...");
                let res = crawl_bili_album(db).await.unwrap_or_else(|err| {
                    error!("{}", err);
                    SqliteQueryResult::default()
                });
                pb.finish_with_message(format!("完成，新加入动态 {} 条", res.rows_affected()));

                println!("完成，用时 {}", HumanDuration(started.elapsed()));
            }
            Some(("other", _)) => {}
            _ => {}
        },
        Some(("collect", _collect_matches)) => {
            // collect_bili_album_picture().await;
        },
        Some(("download", _download_matches)) => {
            todo!("下载")
        },
        Some(("calculate", _calculate_matches)) => {
            todo!("计算图片哈希")
        },
        Some(("ui", _)) => { show_ui(); },
        _ => {}
    }
}

async fn init_app() -> Result<(), String> {
    // 初始化环境变量
    init_env();
    // 初始化日志
    init_logger();
    init_database().await;
    Ok(())
}

#[async_std::main]
async fn main() -> Result<(), String> {
    // init_app().await?;
    // let matches = cli().get_matches();
    // handle_matches(matches).await;

    let test_str = r#"{"test1": 1, "test2": 2}"#;
    let v = serde_json::json!(test_str);
    println!("{}", v);

    Ok(())
}